class MatrixView(QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)    
        self.ui=None
        self.m_beginP=None
        self.m_endP=None
        self.m_bmove=False
        self.m_brelease=False
        self.ui.matrixViewTable.viewport().installEventFilter(self)
        for  i in range(len(self.ui.matrixViewTable.columnCount()):
            self.ui.matrixViewTable.setColumnWidth(i,COL_WIDTH);
            #设置第8列为间隔行，不允许点击或选择
            if(i == NULL_COL):
                itm1 =  QTableWidgetItem();
                self.ui.matrixViewTable.setItem(0,i,itm1);
                itm1.setFlags(Qt.NoItemFlags)
                itm2 = QTableWidgetItem()
                self.ui.matrixViewTable.setItem(1,i,itm2);
                itm2.setFlags(Qt.NoItemFlags);
                continue
            item = QTableWidgetItem();
            self.ui.matrixViewTable.setItem(0,i,item);
            #使用委托显示图片
            #item->setData(Qt::DisplayRole,QVariant::fromValue<QPixmap>(QPixmap(pixmap).scaled(30,30)));
            item2 = QTableWidgetItem();
            self.ui.matrixViewTable.setItem(1,i,item2);
            #item2->setData(Qt::DisplayRole,QVariant::fromValue<QPixmap>(QPixmap(pixmap).scaled(30,30)));
    def InitTableWidget(self):
        pass
    #在eventFilter中获取tablewidget的鼠标按下、移动，释放事件，进行画线，在画线之前进行画图。此处画图的效果与法三的效果一样，且可以在图上面画线。如果不需要处理鼠标事件，此处可以忽略3个鼠标事件的判断。

    def eventFilter(QObject *object, QEvent *event)
    {
        #   qDebug("%s type:%d",object->objectName().toStdString().c_str(),event->type());
        if(object->objectName()!=QString("qt_scrollarea_viewport"))
        {
            return QWidget::eventFilter(object,event);
        }
        if(event->type() == QEvent::MouseButtonPress)
        {
            if(IsMouseInTableWidget(event,m_beginP))
            {
                m_endP = m_beginP;
                update();
            }
        }
        if(event->type() == QEvent::MouseButtonRelease)
        {
            IsMouseInTableWidget(event,m_endP);
            m_brelease = true;
            SetPointToCenter(m_endP);
            update();
        }
        if(event->type() == QEvent::MouseMove)
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            //不进行判断左右键，如果判断左右键，会导致m_endP有时无值，画出的线断断续续
            m_endP = mouseEvent->pos();
            m_bmove = true;
            update();
        }
        if(event->type() == QEvent::Paint)
        {
            QPainter paint(ui->matrixViewTable->viewport());
            //使用paint事件在表格中画图
            int w = COL_WIDTH;
            int h = ui->matrixViewTable->rowHeight(0);
            for(int i=0; i<ui->matrixViewTable->columnCount()-1; i++)
            {
                int x = i>=NULL_COL ? i*COL_WIDTH+NULL_COL_WIDTH : i*COL_WIDTH;
                int y = 0;
                int y1 = ui->matrixViewTable->rowHeight(0);
                QPixmap pix(":/image/grid");
                paint.drawPixmap(QRect(x,y,w,h),pix);
                QPixmap pix1(":/image/grid");
                paint.drawPixmap(QRect(x,y1,w,h),pix1);
            }
            //在表格中画线，线随鼠标动
            if(m_bmove)
            {
                QPen pen(Qt::black,5);
                paint.setPen(pen);
                SetPointToCenter(m_beginP); //取得鼠标最接近项的中心点
                paint.drawPoint(m_beginP);
                QPen pen1(Qt::black,3);
                paint.setPen(pen1);
                paint.drawLine(m_beginP,m_endP);
                QPen pen2(Qt::black,5);
                paint.setPen(pen2);
                paint.drawPoint(m_endP);
            }
            if(m_brelease)
            {
                m_bmove = false;
                m_brelease = false;
            }
        }
        //此处必须返回基类的eventFilter，以让基类有机会进行处理其他事情，否则单单返回true，Qtablewidget上面将无其他东西显示
        return QWidget::eventFilter(object,event);
    }


//判断鼠标按下的点是否在表格内，可无需关注

bool MatrixView::IsMouseInTableWidget(QEvent *event, QPoint &point)
{
    if(event->type() == QEvent::MouseButtonPress  ||
       event->type() == QEvent::MouseButtonRelease||
       event->type() == QEvent::MouseMove)
    {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        if(mouseEvent->button() == Qt::LeftButton)
        {
            QPoint p = mouseEvent->pos();
            //检查鼠标位置是否点在列表的项中，需要考虑中间空白间隔的那列除外
            int col = p.x()/COL_WIDTH>=NULL_COL ? (p.x()+NULL_COL_WIDTH)/COL_WIDTH : p.x()/COL_WIDTH;
            int row = p.y()/ui->matrixViewTable->rowHeight(0);
            if(col<ui->matrixViewTable->columnCount() && row<ui->matrixViewTable->rowCount())
            {
                if(col != NULL_COL)
                {
                    point = p;
                    return true;
                }
            }
        }
    }
    return false;
}
//取得最靠近该点的项的中心点，可无需关注
void MatrixView::SetPointToCenter(QPoint &point)
{
    int x = 0;
    if(point.x()/COL_WIDTH < NULL_COL)
    {
        x = point.x()/COL_WIDTH*COL_WIDTH + COL_WIDTH/2;
    }
    else
    {
        //因为第8列是空列，所以要排除这一列，先将point所在的x坐标减去8列前的部分，得到超出8列后的部分，就可以按照取中心点的方法取得这超出后部分的中心点，再加上8列前部分的位置，就得到最终的中心点
        int null_col_end_x = NULL_COL*COL_WIDTH + NULL_COL_WIDTH;
        x = null_col_end_x + (point.x()-null_col_end_x)/COL_WIDTH*COL_WIDTH + COL_WIDTH/2;
    }
    int h = ui->matrixViewTable->rowHeight(0);
    int y = point.y()/h*h + h/2;
    point = QPoint(x,y);
}
